package com.xbongbong.paas.toolbox.helper;

import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.NamedThreadFactory;
import com.xbongbong.saas.constant.BasicConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * 线程池帮助类
 * @author 章华隽
 * @date 2017-08-23 15:02
 */
public class ThreadPoolHelper {
    private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolHelper.class);
    protected static final String TAG = "ThreadPoolHelper";

    private static ThreadPoolHelper instance;

    public static ThreadPoolHelper getInstance() {
        if (instance == null) {
            synchronized (ThreadPoolHelper.class) {
                if (instance == null) {
                    instance = new ThreadPoolHelper();
                }
            }
        }
        return instance;
    }

    private ThreadPoolHelper() {
    }


    /**
     * 向线程池提交任务
     *
     * @param executor 类内部线程池
     * @param task 线程的执行任务
     */
    public void submitExecutorRunnable(ExecutorService executor, Thread task) {
        if (BasicConstant.DEBUG) {
            catchExecutorException(executor, task);
        } else {
            executor.execute(task);
        }
    }

    /**
     * 向线程池提交任务
     *
     * @param threadPool Spring bean 线程池
     * @param task 线程的执行任务
     */
    public void submitExecutorRunnable(ThreadPoolTaskExecutor threadPool, Runnable task) {
        // TODO 章华隽 2017-12月之前 上线前取消 线程池 的异常捕获
        if (BasicConstant.DEBUG) {
            catchThreadPoolException(threadPool, task);
        } else {
            threadPool.execute(task);
        }
    }

    /**
     * 捕捉线程池中的异常情况
     *
     * @param timedTask 线程的执行任务
     */
    private void catchExecutorException(ExecutorService executor, Thread timedTask) {
        if (executor.isShutdown()) {
            executor =
                    Executors.newFixedThreadPool(8, new NamedThreadFactory("xbb-timedTask-test-Executor"));
        }
        List<Future<String>> resultList = new ArrayList<>();
        Future<String> future = (Future<String>) executor.submit(timedTask);
        resultList.add(future);
        executor.shutdown();
        // 遍历任务的结果
        for (Future<String> fs : resultList) {
            try {
                // 打印各个线程（任务）执行的结果
                LOG.info("【Executor 构造线程池】" + timedTask.getName() + "线程的执行结果：" + fs.get());
            } catch (InterruptedException e) {
                LOG.error("线程池捕获异常 InterruptedException，当前时间：" + DateUtil.getString(), e);
                // 恢复中断状态
                Thread.currentThread().interrupt();
            } catch (ExecutionException e) {
                executor.shutdownNow();
                LOG.error("线程池捕获异常 ExecutionException，当前时间：" + DateUtil.getString(), e);
            }
        }
    }

    /**
     * 捕捉线程池中的异常情况
     *
     * @param timedTask 线程的执行任务
     */
    private void catchThreadPoolException(ThreadPoolTaskExecutor threadPool, Runnable timedTask) {
        List<Future<String>> resultList = new ArrayList<>();
        Future<String> future = (Future<String>) threadPool.submit(timedTask);
        resultList.add(future);
        // 遍历任务的结果
        for (Future<String> fs : resultList) {
            try {
                // 打印各个线程（任务）执行的结果
                LOG.info("【Spring Bean 线程池】" + threadPool.getThreadNamePrefix() + "线程的执行结果：" + fs.get());
            } catch (InterruptedException e) {
                LOG.error("线程池捕获异常 InterruptedException，当前时间：" + DateUtil.getString(), e);
                // 恢复中断状态
                Thread.currentThread().interrupt();
            } catch (ExecutionException e) {
                LOG.error("线程池捕获异常 ExecutionException，当前时间：" + DateUtil.getString(), e);
            }
        }
    }
}
